﻿using Microsoft.Rtc.Collaboration;
using Microsoft.Rtc.Collaboration.Presence;
using Microsoft.Rtc.Signaling;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mime;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace MSFT_SAMPLE_Scheduler
{
    internal class UCMAHelper
    {


        private ServerPlatformSettings _platformSettings;

        private CollaborationPlatform _platform;

        private ApplicationEndpointSettings _endpointSettings;

        private ApplicationEndpoint _endpoint;

        private const string _applicationUserAgent = "UCMASampleApp";

        private string _applicationHostFQDN = "Lastcenturion";

        private int _applicationHostPort = 55555;

        private string _computerGRUU = "sip:LastCenturion@cloudontap.net;gruu;opaque=srvr:consolescheduler:I3XmmElfelKPcvjdJ5iY0QAA";

        private string _certificateFriendlyName = "lastcenturion";

        private X509Certificate2 _certificate;

        private string _endpointOwnerURI;

        private string _registrarFQDN;

        private int _registrarPort;


        private const string _sipPrefix = "sip:";
        private const string delegateString = "<setDelegates xmlns=\"http://schemas.microsoft.com/2007/09/sip/delegate-management\" version=\"{0}\"> <delegate uri=\"{1}\" action=\"{2}\"/> </setDelegates>";
        private const string delegateSubscriptionContext = "<subscriptionContext  xmlns=\"http://schemas.microsoft.com/2008/09/sip/SubscriptionContext\" majorVersion=\"1\" minorVersion=\"0\"> <delegation/> </subscriptionContext>";
        private static ManualResetEvent _sampleFinished;
        private static CollaborationPlatform _serverCollabPlatform;
        private UserEndpoint _userEndpoint;

        static UCMAHelper()
        {
            UCMAHelper._sampleFinished = new ManualResetEvent(false);
        }
        public UCMAHelper()
        {
        }
        public void CreateAndStartServerPlatform()
        {
            _certificate = GetLocalCertificate("lastcenturion");
            _platformSettings = new ServerPlatformSettings(_applicationUserAgent,
                    _applicationHostFQDN,
                    _applicationHostPort,
                    _computerGRUU,
                    _certificate);
            _platform = new CollaborationPlatform(_platformSettings);
            UCMAHelper._serverCollabPlatform = _platform;
            IAsyncResult asyncResult = UCMAHelper._serverCollabPlatform.BeginStartup(null, _serverCollabPlatform);
            UCMAHelper._serverCollabPlatform.EndStartup(asyncResult);
        }

        public UserEndpoint CreateUserEndpoint(UserEndpointSettings userEndpointSettings)
        {
            this._userEndpoint = new UserEndpoint(UCMAHelper._serverCollabPlatform, userEndpointSettings);
            return this._userEndpoint;
        }

        public bool DoSelfSub(UserEndpoint userEndpoint)
        {
            IAsyncResult asyncResult = userEndpoint.LocalOwnerPresence.BeginSubscribe(null, null);
            userEndpoint.LocalOwnerPresence.EndSubscribe(asyncResult);
            Thread.Sleep(2000);
            return true;
        }

        public bool EstablishUserEndpoint(UserEndpoint userEndpoint)
        {
            List<SignalingHeader> signalingHeaders = new List<SignalingHeader>()
			{
				SignalingHeader.MicrosoftSupportedForking,
				SignalingHeader.MicrosoftSupportedPresence,
				SignalingHeader.MicrosoftSupportedEventCategories
			};
            IAsyncResult asyncResult = userEndpoint.BeginEstablish(signalingHeaders, null, null);
            userEndpoint.EndEstablish(asyncResult);
            return true;
        }

        // Whats the purpose of this?
        public static X509Certificate2 GetLocalCertificate(string friendlyName)
        {
            X509Store x509Store = new X509Store(StoreLocation.LocalMachine);
            x509Store.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection certificates = x509Store.Certificates;
            x509Store.Close();
            X509Certificate2Enumerator enumerator = certificates.GetEnumerator();
            while (enumerator.MoveNext())
            {
                X509Certificate2 current = enumerator.Current;
                if (!current.FriendlyName.Equals(friendlyName, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }
                return current;
            }
            return null;
        }

        private void PublishDelegateUpdate(UserEndpoint userEndpoint, string delegateUri, string action)
        {
            int num = 1;
            for (int i = 0; i < 2; i++)
            {
                try
                {
                    string str = string.Format("<setDelegates xmlns=\"http://schemas.microsoft.com/2007/09/sip/delegate-management\" version=\"{0}\"> <delegate uri=\"{1}\" action=\"{2}\"/> </setDelegates>", num, delegateUri, action);
                    // Looks like we should be replacing this with Microsoft.Rtc.Signaling.RealTimeEndpoint
                    SipServiceRequest sipServiceRequest = new SipServiceRequest(userEndpoint.InnerEndpoint, new ContentType("application/msrtc-setdelegate+xml"), Encoding.UTF8.GetBytes(str));
                    sipServiceRequest.EndService(sipServiceRequest.BeginService(null, null));
                }
                catch (FailureResponseException failureResponseException1)
                {
                    FailureResponseException failureResponseException = failureResponseException1;
                    if (failureResponseException.ResponseData.ResponseCode != 409)
                    {
                        throw;
                    }
                    else
                    {
                        Regex regex = new Regex("<operation[^>]*curVersion=[^>](?<1>[0-9]+)[^<]+>", RegexOptions.IgnoreCase);
                        MatchCollection matchCollections = regex.Matches(failureResponseException.ResponseData.GetMessageBodyString());
                        if (matchCollections.Count == 1)
                        {
                            Match item = matchCollections[0];
                            int.TryParse(item.Groups[1].Captures[0].Value, out num);
                        }
                        else
                        {
                            num = 1;
                        }
                    }
                }
            }
        }

        public void PublishRoutingCategory(UserEndpoint userEndpoint, List<PresenceCategory> items)
        {
            IAsyncResult asyncResult = userEndpoint.LocalOwnerPresence.BeginPublishPresence(items, null, null);
            userEndpoint.LocalOwnerPresence.EndPublishPresence(asyncResult);
        }

        public void RemoveDelegate(UserEndpoint userEndpoint, string oldDelegate)
        {
            this.PublishDelegateUpdate(userEndpoint, oldDelegate, "remove");
            ContainerUpdateOperation containerUpdateOperation = new ContainerUpdateOperation(300);
            containerUpdateOperation.DeleteUri(oldDelegate);
            List<ContainerUpdateOperation> containerUpdateOperations = new List<ContainerUpdateOperation>()
			{
				containerUpdateOperation
			};
            IAsyncResult asyncResult = userEndpoint.LocalOwnerPresence.BeginUpdateContainerMembership(containerUpdateOperations, null, null);
            userEndpoint.LocalOwnerPresence.EndUpdateContainerMembership(asyncResult);
        }

        internal void ShutdownPlatform()
        {
            if (UCMAHelper._serverCollabPlatform != null)
            {
                IAsyncResult asyncResult = UCMAHelper._serverCollabPlatform.BeginShutdown(null, null);
                UCMAHelper._serverCollabPlatform.EndShutdown(asyncResult);
            }
        }
    }
}
